home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / Z4CSFILE.CPP < prev    next >
C/C++ Source or Header  |  1995-09-19  |  15KB  |  468 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    z4csfile.cpp
  5. //   Title:    ZIP+4 Engine
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //    This module contains code for the class Z4_CS_FILE.
  24. //
  25. //    The code in this module may be written in C++ or C.
  26. //
  27. //    This module is portable to:
  28. //        DOS 3.X+
  29. //        MS Windows 3.X+
  30. //        OS/2 2.X+
  31. //        OS/2 2.0 PM
  32. //
  33. //    The following compilers are supported:
  34. //        MSC 6.0A
  35. //        MSC/C++ 7.0
  36. //        Borland C++ 3.1 for DOS
  37. //        Borland C++ 1.0 for OS/2 2.X
  38. //
  39. //----------------------------------------------------------------------------
  40. #include <z4.h>
  41.  
  42.  
  43. //----------------------------------------------------------------------------
  44. //    Globals
  45. //----------------------------------------------------------------------------
  46. PCSZ Z4_CS_FILE::pcszLogical = "City/State";
  47.  
  48.  
  49. //----------------------------------------------------------------------------
  50. //   Description:    Default constructor
  51. //    Parameters:
  52. //       Returns:    
  53. //----------------------------------------------------------------------------
  54. FN_M Z4_CS_FILE::Z4_CS_FILE()
  55. {
  56.     Z4_CS_FILE::Initialize(CL_INIT_CLASS);
  57. }
  58.  
  59.  
  60. //----------------------------------------------------------------------------
  61. //   Description:    Copy constructor
  62. //    Parameters:    rcz4_cs_file        Reference to object to copy.
  63. //       Returns:    
  64. //----------------------------------------------------------------------------
  65. FN_M Z4_CS_FILE::Z4_CS_FILE(RCZ4_CS_FILE rcz4_cs_file)
  66. {
  67.     Z4_CS_FILE::Initialize(CL_INIT_CLASS);
  68.     *this = rcz4_cs_file;
  69. }
  70.  
  71.  
  72. //----------------------------------------------------------------------------
  73. //   Description:    Destructor
  74. //    Parameters:
  75. //       Returns:    
  76. //----------------------------------------------------------------------------
  77. FN_M Z4_CS_FILE::~Z4_CS_FILE()
  78. {
  79.     Z4_CS_FILE::Destroy(FALSE);
  80. }
  81.  
  82.  
  83. //----------------------------------------------------------------------------
  84. //   Description:    Find the best city record for a given five digit ZIP record.
  85. //              Selects the matching last line number with the highest
  86. //            facility code.
  87. //    Parameters:    
  88. //       Returns:    TRUE if valid
  89. //----------------------------------------------------------------------------
  90. BOOL FN_M Z4_CS_FILE::Best(RZ4_CS rz4_cs, RZ4_Z5 rz4_z5, PCSZ pcszLastLine)
  91. {
  92.     if (IsError())                                // Check error condition
  93.         return FALSE;
  94.  
  95.     if (pcszLastLine == NULL || strlen(pcszLastLine) != MAX_LAST_LINE)
  96.         pcszLastLine = "000000";
  97.  
  98.     SIZET iBest, iCur;
  99.     Z4_FACILITY facility = Z4_FACILITY_OTHER;
  100.     BOOL fLastLine = FALSE;
  101.     Assert(rz4_z5.cCities);
  102.     for (SIZET i = 0; i < rz4_z5.cCities; ++i)
  103.         {
  104.         if (!Record(rz4_cs, rz4_z5.arecid[i]))
  105.             return FALSE;
  106.  
  107.         iCur = i;
  108.         BOOL fLastLineCur = stricmp(pcszLastLine, rz4_cs.szLastLine) == 0;
  109.         if (i == 0
  110.         || (!fLastLine && (fLastLineCur || rz4_cs.facility > facility))
  111.         || (fLastLine && fLastLineCur && rz4_cs.facility > facility))
  112.             {
  113.             iBest = i;
  114.             facility    = rz4_cs.facility;
  115.             fLastLine = fLastLineCur;
  116.  
  117.             if (fLastLineCur && rz4_cs.facility == Z4_FACILITY_PO)
  118.                 break;
  119.             }
  120.         }
  121.                                                     // Read best record
  122.     if (iCur != iBest && !Record(rz4_cs, rz4_z5.arecid[iBest]))
  123.         return FALSE;
  124.  
  125.     return TRUE;
  126. }
  127.  
  128.  
  129. //----------------------------------------------------------------------------
  130. //   Description:    Destroy object. Free any resources used by object.
  131. //                          Normally called by destructor.
  132. //                        Should allow multiple calls from various classes.
  133. //    Parameters:    fDestroyAll        Destroy parents also?
  134. //                                            Default is TRUE.
  135. //       Returns:    TRUE if successful.
  136. //----------------------------------------------------------------------------
  137. BOOL FN_M Z4_CS_FILE::Destroy(BOOL fDestroyAll)
  138. {
  139.     DioCloseLogical(hlf);
  140.     DioCloseLogical(hlfRecNo);
  141.     Z4CSExpandTerminate(&z4_cs_blk);
  142.     Z4_CS_FILE::Initialize(CL_INIT_CLASS_VARS);
  143.     if (fDestroyAll)                            // Destroy parent.
  144.         Z4_CS_FILE_PARENT::Destroy(fDestroyAll);                    
  145.     return TRUE;
  146. }
  147.  
  148.  
  149. //----------------------------------------------------------------------------
  150. //   Description:    Find first record in a specified block.
  151. //    Parameters:    z4_cs            Buffer for record
  152. //                        state            State code.
  153. //                        pcszCity     City name or NULL.
  154. //                                        Default is NULL.
  155. //       Returns:    TRUE if valid
  156. //----------------------------------------------------------------------------
  157. BOOL FN_M Z4_CS_FILE::Find(RZ4_CS rz4_cs, Z4_STATE state, PCSZ pcszCity)
  158. {
  159.     if (IsError())                                // Check error condition
  160.         return FALSE;
  161.  
  162.     Assert(pcszCity && state != Z4_ST_INVALID);
  163.  
  164.     if (!First(rz4_cs, state, pcszCity))
  165.         return FALSE;
  166.         // SHORT sResult;   org code
  167.         INT sResult;
  168.         do
  169.         {
  170.         sResult = stricmp(rz4_cs.szCity, pcszCity);
  171.         if (sResult == 0 && rz4_cs.state == state)
  172.             return TRUE;
  173.         }
  174.     while (rz4_cs.state == state && sResult < 0 && Next(rz4_cs));
  175.     return FALSE;
  176. }
  177.  
  178.  
  179. //----------------------------------------------------------------------------
  180. //   Description:    Find first record in a specified block.
  181. //    Parameters:    z4_cs            Buffer for record
  182. //                        state            State code.
  183. //                        pcszCity     City name or NULL.
  184. //                                        Default is NULL.
  185. //       Returns:    TRUE if valid
  186. //----------------------------------------------------------------------------
  187. BOOL FN_M Z4_CS_FILE::First(RZ4_CS rz4_cs, Z4_STATE state, PCSZ pcszCity)
  188. {
  189.     if (IsError())                                // Check error condition
  190.         return FALSE;
  191.  
  192.     BYTE bKey[MAX_CS_KEY];
  193.     Z4CSKey(bKey, state, pcszCity);
  194.  
  195.     LONG lIndexBlock;
  196.     if (!DioReadIndex(hlf, bKey, sizeof(bKey), &lIndexBlock))
  197.         return SetError();
  198.  
  199.     if (First(rz4_cs, lIndexBlock))
  200.         {
  201.         do
  202.             {
  203.             BYTE bKey2[MAX_CX_KEY];
  204.             Z4CXKey(bKey2, rz4_cs.state, rz4_cs.szCity);
  205.  
  206.             if (memcmp(bKey2, bKey, MAX_CS_KEY) >= 0)
  207.                 return TRUE;
  208.             }
  209.         while (Next(rz4_cs));
  210.         return !IsError();
  211.         }
  212.     return FALSE;
  213. }
  214.  
  215.  
  216. //----------------------------------------------------------------------------
  217. //   Description:    Find first record in a specified block.
  218. //    Parameters:    z4_cs            Buffer for record
  219. //                        _lBlock        Block to read
  220. //                                        Default is 0.
  221. //       Returns:    TRUE if valid
  222. //----------------------------------------------------------------------------
  223. BOOL FN_M Z4_CS_FILE::First(RZ4_CS rz4_cs, LONG _lBlock)
  224. {
  225.     if (IsError())                                // Check error condition
  226.         return FALSE;
  227.  
  228.     if (_lBlock >= lBlocks)                    // End of file!
  229.         return FALSE;
  230.  
  231.     if (!fBlock || lBlock != _lBlock)
  232.         {
  233.         lBlock = _lBlock;
  234.         fBlock = TRUE;
  235.         fOffset = FALSE;
  236.         if (!DioSeekBlock(hlf, lBlock)
  237.         || !DioReadBlock(hlf, NULL, &pb, NULL)
  238.         || !Z4CSExpandReset(&z4_cs_blk, pb, (SIZET)usBlockSize))
  239.             return SetError();
  240.         }
  241.     if (fOffset && usOffset == 0)
  242.         {
  243.         rz4_cs = z4_cs_blk.cs;                // Record was the existing expanded
  244.         return TRUE;                            //  record
  245.         }
  246.     if (fOffset)                                // Reset expander for current block
  247.         if (!Z4CSExpandReset(&z4_cs_blk, pb, (SIZET)usBlockSize))
  248.             return SetError();
  249.                                                     // Expand first record
  250.     if (!Z4CSExpand(&z4_cs_blk, &rz4_cs))
  251.         return SetError();
  252.     fOffset = TRUE;
  253.     usOffset = 0;
  254.     rz4_cs.recid.lBlock = lBlock;
  255.     rz4_cs.recid.usOffset = usOffset;
  256.     return TRUE;
  257. }
  258.  
  259.  
  260. //----------------------------------------------------------------------------
  261. //   Description:    Initialize object. 
  262. //                          Normally called by constructor.
  263. //                        Should allow multiple calls from various classes.
  264. //    Parameters:    sInit        Initialization code. May be one of the following:
  265. //                                        CL_INIT_CLASS            Reset class variables and
  266. //                                                                    and dynamic allocations for
  267. //                                                                    this class only.
  268. //                                        CL_INIT_CLASS_VARS    Reset class variables for
  269. //                                                                    this class only.
  270. //                                        CL_INIT_VARS            Reset class variables for
  271. //                                                                    this class only.
  272. //                                        CL_INIT_ALL                Initialize class and all 
  273. //                                                                    parent class, including
  274. //                                                                    dynamic memory allocation.
  275. //                                    Default is CL_INIT_ALL
  276. //       Returns:    TRUE if successful.
  277. //----------------------------------------------------------------------------
  278. BOOL FN_M Z4_CS_FILE::Initialize(SHORT sInit)
  279. {
  280.     if (sInit == CL_INIT_VARS || sInit == CL_INIT_ALL)
  281.         Z4_CS_FILE_PARENT::Initialize(sInit);
  282.  
  283.     hlf = -1;
  284.     hlfRecNo = -1;
  285.     lRecs = -1;
  286.     memset(&z4_cs_blk, 0, sizeof(z4_cs_blk));
  287.     fBlock = FALSE;
  288.     fOffset = FALSE;
  289.     return TRUE;
  290. }
  291.  
  292.  
  293. //----------------------------------------------------------------------------
  294. //   Description:    Check if object is in error state.
  295. //                          IsValid() && IsError() MUST NOT BE DEPENDENT ON ONE ANOTHER.
  296. //    Parameters:
  297. //       Returns:    TRUE if in error state.
  298. //----------------------------------------------------------------------------
  299. BOOL FN_M Z4_CS_FILE::IsError() const
  300. {
  301.     return Z4_CS_FILE_PARENT::IsError()
  302.         || DioIsError(hlf)
  303.         || DioIsError(hlfRecNo);
  304. }
  305.  
  306.  
  307. //----------------------------------------------------------------------------
  308. //   Description:    Check if object is valid
  309. //                          IsValid() && IsError() MUST NOT BE DEPENDENT ON ONE ANOTHER.
  310. //    Parameters:
  311. //       Returns:    TRUE if valid
  312. //----------------------------------------------------------------------------
  313. BOOL FN_M Z4_CS_FILE::IsValid() const
  314. {
  315.     return Z4_CS_FILE_PARENT::IsValid()
  316.         && DioIsValid(hlf)
  317.         && DioIsValid(hlfRecNo);
  318. }
  319.  
  320.  
  321. //----------------------------------------------------------------------------
  322. //   Description:    Read next record
  323. //    Parameters:    z4_cs        Buffer for record
  324. //       Returns:    TRUE if record found. FALSE if at end of file.
  325. //----------------------------------------------------------------------------
  326. BOOL FN_M Z4_CS_FILE::Next(RZ4_CS rz4_cs)
  327. {
  328.     if (IsError())                                // Check error condition
  329.         return FALSE;
  330.     Assert(fBlock && fOffset);
  331.                                                     // Expand next record or goto next block
  332.     if (!Z4CSExpand(&z4_cs_blk, &rz4_cs))
  333.         return First(rz4_cs, lBlock + 1);
  334.  
  335.     usOffset++;
  336.     rz4_cs.recid.lBlock = lBlock;
  337.     rz4_cs.recid.usOffset = usOffset;
  338.     return TRUE;
  339. }
  340.  
  341.  
  342. //----------------------------------------------------------------------------
  343. //   Description:    Open CS file
  344. //    Parameters:
  345. //       Returns:    TRUE if valid
  346. //----------------------------------------------------------------------------
  347. BOOL FN_M Z4_CS_FILE::Open()
  348. {
  349.         if (!Z4_INQ::Start()
  350.         || !DioOpenIndex(pcszLogical, &hlf)
  351.     || !DioCacheSet(hlf, 1)
  352.     || !DioGetRecords(hlf, &lRecs)
  353.     || !DioGetBlockSize(hlf, &usBlockSize)
  354.     || !DioGetBlocks(hlf, &lBlocks)
  355.     || !DioOpenRecNo(pcszLogical, &hlfRecNo)
  356.     || !Z4CSExpandInitialize(&z4_cs_blk))
  357.         return SetError();
  358.  
  359.     return TRUE;
  360. }
  361.  
  362.  
  363. //----------------------------------------------------------------------------
  364. //   Description:    Assignment operator
  365. //                          NOTE: Don't copy object into self
  366. //    Parameters:    rcz4_cs_file        Reference to right value.
  367. //       Returns:    Reference to new object.
  368. //----------------------------------------------------------------------------
  369. RCZ4_CS_FILE FN_M Z4_CS_FILE::operator=(RCZ4_CS_FILE rcz4_cs_file)
  370. {
  371.     if (this != &rcz4_cs_file)
  372.         {
  373.         Invalid("Z4_CS_FILE::operator=");
  374.         }
  375.     return (RCZ4_CS_FILE)*this;
  376. }
  377.  
  378.  
  379. //----------------------------------------------------------------------------
  380. //   Description:    Read a particular record from the file
  381. //    Parameters:    z4_cs            Buffer for record
  382. //                        lRec            Record to read.
  383. //                                        If < 0, return current record
  384. //                                        Default is -1.
  385. //       Returns:    TRUE if record found. FALSE if at end of file.
  386. //----------------------------------------------------------------------------
  387. BOOL FN_M Z4_CS_FILE::Record(RZ4_CS rz4_cs, LONG lRec)
  388. {
  389.     RECID recid;
  390.  
  391.     if (IsError())                                // Check error condition
  392.         return FALSE;
  393.     if (lRec >= lRecs)
  394.         return FALSE;
  395.     if (lRec < 0)                                // Return current record 
  396.         {
  397.         if (fBlock && fOffset)
  398.             {
  399.             rz4_cs = z4_cs_blk.cs;                
  400.             return TRUE;
  401.             }
  402.         return FALSE;
  403.         }                                            // Convert to record id
  404.     if (!DioRecNo2RecId(hlfRecNo, lRec, &recid))
  405.         return SetError();
  406.  
  407.     return Record(rz4_cs, recid);
  408. }
  409.  
  410.  
  411. //----------------------------------------------------------------------------
  412. //   Description:    Read a particular record from the file by record id
  413. //    Parameters:    z4_cs            Buffer for record
  414. //                        recid            Record id to read.
  415. //       Returns:    TRUE if record found. FALSE if at end of file.
  416. //----------------------------------------------------------------------------
  417. BOOL FN_M Z4_CS_FILE::Record(RZ4_CS rz4_cs, RECID recid)
  418. {
  419.     if (IsError())                                // Check error condition
  420.         return FALSE;
  421.                                                     // Move to correct block
  422.     if (!fBlock || recid.lBlock != lBlock)
  423.         if (!First(rz4_cs, recid.lBlock))
  424.             return FALSE;
  425.     if (recid.usOffset < usOffset)        // If past desired record, restart 
  426.         {                                            //  from offset 0
  427.         if (!Z4CSExpandReset(&z4_cs_blk, pb, (SIZET)usBlockSize)
  428.         || !Z4CSExpand(&z4_cs_blk, &rz4_cs))
  429.             return SetError();
  430.  
  431.         usOffset = 0;
  432.         fOffset = TRUE;
  433.         }                        
  434.     rz4_cs = z4_cs_blk.cs;                // Search for desired record
  435.     for (; usOffset < recid.usOffset; usOffset++)
  436.         if (!Z4CSExpand(&z4_cs_blk, &rz4_cs))
  437.             return SetError();
  438.     rz4_cs.recid.lBlock = lBlock;
  439.     rz4_cs.recid.usOffset = usOffset;
  440.     return TRUE;
  441. }
  442.  
  443.  
  444. //----------------------------------------------------------------------------
  445. //   Description:    
  446. //    Parameters:    
  447. //       Returns:    Record number of current record or -1
  448. //----------------------------------------------------------------------------
  449. LONG FN_M Z4_CS_FILE::RecordNo()
  450. {
  451.     if (IsError())                                // Check error condition
  452.         return -1;
  453.     RECID recid;
  454.     recid.usOffset = usOffset;
  455.     recid.lBlock = lBlock;
  456.     LONG lRec;
  457.     if (!DioRecId2RecNo(hlfRecNo, &lRec, &recid))
  458.         {
  459.         SetError();
  460.         return -1;
  461.         }
  462.     return lRec;
  463.  
  464. }
  465. //----------------------------------------------------------------------------
  466. //------------------------------- End of File --------------------------------
  467. //----------------------------------------------------------------------------
  468.